package com.hzncc.flowable_diboot.payment.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.diboot.core.entity.Dictionary;
import com.diboot.core.service.DictionaryService;
import com.diboot.core.service.impl.DictionaryServiceExtImpl;
import com.diboot.core.util.BeanUtils;
import com.diboot.core.util.V;
import com.diboot.core.util.S;
import com.diboot.core.util.ContextHolder;
import com.diboot.core.vo.JsonResult;
import com.diboot.core.vo.LabelValue;
import com.diboot.core.vo.Pagination;
import com.diboot.core.controller.BaseCrudRestController;
import com.diboot.file.util.ExcelHelper;
import com.diboot.iam.annotation.OperationCons;
import com.diboot.iam.annotation.BindPermission;
import com.diboot.iam.annotation.Log;
import com.hzncc.flowable_diboot.delivery.excel.listener.DeliveryDetailImportListener;
import com.hzncc.flowable_diboot.delivery.excel.model.DeliveryDetailImportModel;
import com.hzncc.flowable_diboot.delivery.vo.DeliveryDetailDetailVO;
import com.hzncc.flowable_diboot.enums.BpmProcessInstanceStatusEnum;
import com.hzncc.flowable_diboot.excel.service.MultiSheetExcelImportService;
import com.hzncc.flowable_diboot.payment.entity.PaymentContract;
import com.hzncc.flowable_diboot.payment.excel.listener.PaymentRegisterImportListener;
import com.hzncc.flowable_diboot.payment.excel.model.PaymentRegisterExportModel;
import com.hzncc.flowable_diboot.payment.excel.model.PaymentRegisterImportModel;
import com.hzncc.flowable_diboot.payment.service.PaymentContractService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hzncc.flowable_diboot.payment.entity.PaymentRegister;
import com.hzncc.flowable_diboot.payment.service.PaymentRegisterService;
import com.hzncc.flowable_diboot.payment.vo.PaymentRegisterDetailVO;
import com.hzncc.flowable_diboot.payment.vo.PaymentRegisterListVO;
import com.hzncc.flowable_diboot.payment.dto.PaymentRegisterDTO;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 回款登记 相关rest接口
 *
 * @author MyName
 * @version 1.0
 * @date 2024-10-15
 * Copyright © MyCorp
 */
@Slf4j
@RequestMapping("/payment-manage/payment-register")
@BindPermission(name = "回款登记")
@RestController
public class PaymentRegisterController extends BaseCrudRestController<PaymentRegister> {

    @Autowired
    private PaymentRegisterService paymentRegisterService;

    @Autowired
    private PaymentContractService paymentContractService;


    /**
     * 下载示例文件
     *
     * @param response
     * @throws Exception
     */
    @Log(operation = "导入回款登记示例文件下载")
    @BindPermission(name = "导入回款登记示例文件下载", code = OperationCons.CODE_READ)
    @GetMapping("/download-example")
    public void downloadExample(HttpServletResponse response) throws Exception {
        String fileName = "回款登记导入示例.xlsx";
        List<PaymentRegisterImportModel> dataList = new ArrayList<>();
        PaymentRegisterImportModel paymentRegisterImportModel = new PaymentRegisterImportModel();
        paymentRegisterImportModel.setPaymentTime(LocalDate.now());
        paymentRegisterImportModel.setCustomerName("示例客户");
        paymentRegisterImportModel.setPaymentAmount(new BigDecimal(100000));
        paymentRegisterImportModel.setBankName("招行");
        paymentRegisterImportModel.setRemark("示例数据");
        dataList.add(paymentRegisterImportModel);
        ExcelHelper.exportExcel(response, fileName, PaymentRegisterImportModel.class, dataList);
    }

    /**
     * 上传excel并保存
     *
     * @param file
     * @param params
     * @throws Exception
     */
    @Log(operation = "直接导入")
    @BindPermission(name = "直接导入", code = OperationCons.CODE_WRITE)
    @PostMapping("/batch-import")
    public JsonResult<?> batchImport(@RequestParam("file") MultipartFile file, @RequestParam Map<String, Object> params) throws Exception {
        return paymentRegisterService.batchImportPaymentRegister(file, params);
    }

    /**
     * 查询资源对象的列表VO记录
     * <p>
     * url请求参数示例: ?fieldA=abc&pageSize=20&pageIndex=1&orderBy=id
     * </p>
     *
     * @return
     * @throws Exception
     */
    @Log(operation = OperationCons.LABEL_LIST)
    @BindPermission(name = OperationCons.LABEL_LIST, code = OperationCons.CODE_READ)
    @GetMapping()
    public JsonResult<List<PaymentRegisterListVO>> getListVOMapping(PaymentRegisterDTO queryDto, Pagination pagination) throws Exception {
        return super.getViewObjectList(queryDto, pagination, PaymentRegisterListVO.class);
    }

    /**
     * 根据id查询资源对象的详情VO
     *
     * @param id ID
     * @return
     * @throws Exception
     */
    @Log(operation = OperationCons.LABEL_DETAIL)
    @BindPermission(name = OperationCons.LABEL_DETAIL, code = OperationCons.CODE_READ)
    @GetMapping("/{id}")
    public JsonResult<PaymentRegisterDetailVO> getDetailVOMapping(@PathVariable("id") String id) throws Exception {
        PaymentRegisterDetailVO detailVO = paymentRegisterService.getViewObject(id, PaymentRegisterDetailVO.class);
        return JsonResult.OK(detailVO);
    }


    /**
     * 创建资源对象数据
     *
     * @param paymentRegister
     * @return JsonResult
     * @throws Exception
     */
    @Log(operation = OperationCons.LABEL_CREATE)
    @BindPermission(name = OperationCons.LABEL_CREATE, code = OperationCons.CODE_WRITE)
    @PostMapping()
    public JsonResult<?> createModelMapping(@RequestBody PaymentRegister paymentRegister) throws Exception {
        boolean success = paymentRegisterService.createPaymentRegister(paymentRegister);
        log.debug("新建数据 回款登记:{} {}", paymentRegister.getId(), success ? "成功" : "失败");
        return JsonResult.OK(paymentRegister.getId());
    }

    /**
     * 回款登记作废
     *
     * @param id
     * @return
     * @throws Exception
     */
    @Log(operation = OperationCons.LABEL_CREATE)
    @BindPermission(name = OperationCons.LABEL_CREATE, code = OperationCons.CODE_WRITE)
    @PostMapping("/cancel/{id}")
    public JsonResult<?> cancelPaymentRegister(@PathVariable("id") String id) throws Exception {
        boolean success = paymentContractService.cancelPaymentRegister(id);
        return JsonResult.OK(success);
    }

    /**
     * 批量创建资源对象数据
     *
     * @param paymentRegisterList
     * @return JsonResult
     * @throws Exception
     */
    @Log(operation = OperationCons.LABEL_BATCH_UPDATE)
    @BindPermission(name = OperationCons.LABEL_UPDATE, code = OperationCons.CODE_WRITE)
    @PostMapping("/batch")
    public JsonResult<?> batchCreateModelMapping(@RequestBody List<PaymentRegister> paymentRegisterList) throws Exception {
        boolean success = paymentRegisterService.createEntities(paymentRegisterList);
        log.debug("批量新建数据 回款登记 {}", success ? "成功" : "失败");
        return JsonResult.OK(success);
    }

    /**
     * 根据id更新资源对象
     *
     * @param paymentRegister
     * @return JsonResult
     * @throws Exception
     */
    @Log(operation = OperationCons.LABEL_UPDATE)
    @BindPermission(name = OperationCons.LABEL_UPDATE, code = OperationCons.CODE_WRITE)
    @PutMapping("/{id}")
    public JsonResult<?> updateModelMapping(@PathVariable("id") String id, @RequestBody PaymentRegister paymentRegister) throws Exception {
        boolean success = paymentRegisterService.updateEntity(paymentRegister);
        log.debug("更新数据 回款登记:{} {}", id, success ? "成功" : "失败");
        return JsonResult.OK(success);
    }

    /**
     * 根据id删除资源对象
     *
     * @param id
     * @return
     * @throws Exception
     */
    @Log(operation = OperationCons.LABEL_DELETE)
    @BindPermission(name = OperationCons.LABEL_DELETE, code = OperationCons.CODE_WRITE)
    @DeleteMapping("/{id}")
    public JsonResult<?> deleteModelMapping(@PathVariable("id") String id) throws Exception {
        if (paymentContractService.deleteCheck(Collections.singleton(id))) {
            boolean success = paymentRegisterService.deleteEntity(id);
            log.debug("删除数据 回款登记:{} {}", id, success ? "成功" : "失败");
            return JsonResult.OK(success);
        } else {
            return JsonResult.FAIL_VALIDATION("回款登记已使用，无法删除");
        }
    }

    /**
     * 根据ids集合删除资源对象
     *
     * @param ids
     * @return
     * @throws Exception
     */
    @Log(operation = OperationCons.LABEL_BATCH_DELETE)
    @BindPermission(name = OperationCons.LABEL_DELETE, code = OperationCons.CODE_WRITE)
    @PostMapping("/batch-delete")
    public JsonResult<?> deleteEntityMapping(@RequestBody List<String> ids) throws Exception {
        if (paymentContractService.deleteCheck(new HashSet<>(ids))) {
            boolean success = paymentRegisterService.deleteEntities(ids);
            log.debug("批量删除数据 回款登记:{} {}", ids, success ? "成功" : "失败");
            return JsonResult.OK(success);
        } else {
            return JsonResult.FAIL_VALIDATION("回款登记已使用，无法删除");
        }
    }

    /**
     * 检查收款状态
     *
     * @param id
     * @return
     */
    @GetMapping("/check-status/{id}")
    public JsonResult<?> checkPaymentStatus(@PathVariable String id) {
        PaymentRegister entity = paymentRegisterService.getEntity(id);
        if (S.equals(entity.getCerted(), "1")) {
            return JsonResult.FAIL_VALIDATION("已生成回款凭证，无法生成回款凭证");
        }
        if (S.equals(entity.getCategory(), "20")) {
            return JsonResult.FAIL_VALIDATION("该回款登记为预收回款，无法生成回款凭证");
        }
        if (!S.equals(entity.getStatus(), "30")) {
            return JsonResult.FAIL_VALIDATION("该条登记的金额还未认领完，无法生成回款凭证");
        }
        List<PaymentContract> entityList = paymentContractService.getEntityList(paymentContractService.lambdaQuery().eq(PaymentContract::getPaymentRegisterId, id));
        if (entityList.stream()
                .filter(e -> !S.equals(e.getProcessState(), BpmProcessInstanceStatusEnum.CANCEL.getStatus().toString())
                && !S.equals(e.getProcessState(), BpmProcessInstanceStatusEnum.REVOKE.getStatus().toString())
                && !S.equals(e.getProcessState(), BpmProcessInstanceStatusEnum.VOID.getStatus().toString()))
                .anyMatch(e -> !S.equals(e.getProcessState(), BpmProcessInstanceStatusEnum.APPROVE.getStatus().toString())
        )) {
            return JsonResult.FAIL_VALIDATION("该回款有审批未完成或审批未通过的合同收款数据");
        }
        return JsonResult.OK();
    }

    /**
     * 批量检查收款状态
     *
     * @param ids
     * @return
     */
    @GetMapping("/batch-check-status")
    public JsonResult<?> batchCheckPaymentStatus(@RequestParam List<String> ids) {
        List<PaymentRegister> paymentRegisterList = paymentRegisterService.getEntityListByIds(ids);
        if (CollectionUtils.isEmpty(paymentRegisterList)) {
            return JsonResult.FAIL_VALIDATION("回款登记不存在");
        }
        for (PaymentRegister paymentRegister : paymentRegisterList) {
            if (S.equals(paymentRegister.getCerted(), "1")) {
                return JsonResult.FAIL_VALIDATION("已生成回款凭证，无法生成回款凭证");
            }
            if (S.equals(paymentRegister.getCategory(), "20")) {
                return JsonResult.FAIL_VALIDATION("该回款登记为预收回款，无法生成回款凭证");
            }
            if (!S.equals(paymentRegister.getStatus(), "30")) {
                return JsonResult.FAIL_VALIDATION(paymentRegister.getCustomerName() + "登记的金额还未认领完，无法生成回款凭证");
            }
            List<PaymentContract> entityList = paymentContractService.getEntityList(paymentContractService.lambdaQuery().eq(PaymentContract::getPaymentRegisterId, paymentRegister.getId()));
            if (entityList.stream().anyMatch(e -> !S.equals(e.getProcessState(), "2"))) {
                return JsonResult.FAIL_VALIDATION(paymentRegister.getCustomerName() + "回款有审批未完成或审批未通过的合同收款数据");
            }
        }
        return JsonResult.OK();
    }
}